//
// Created by ole on 24-8-27.
//

#include <dlfcn.h>
#include "PluginLoader.h"

#include "BasePlugin.h"
#include "../../utils/Log.h"

void *PluginLoader::load(const std::string &path) const {
    dlerror();
    void *handle = dlopen(path.c_str(), RTLD_LAZY);
    if (!handle) {
        const char *err = dlerror();
        Log::e(TAG, "Loaded plugin " + path + " failed. " + err);
        return nullptr;
    }
    Log::d(TAG, "Loaded plugin " + path + " success.");
    return handle;
}


std::shared_ptr<BasePlugin> PluginLoader::createShared(void *handle) const {
    typedef BasePlugin * (*CreateInstance)();
    const auto create = reinterpret_cast<CreateInstance>(dlsym(handle, "createInstance"));
    const char *err = dlerror();
    if (err) {
        Log::e(TAG, "Failed to load plugin " + std::string(err));
        return nullptr;
    }

    std::shared_ptr<BasePlugin> plugin(create(), [](const BasePlugin *pBase) {
        Log::d("PluginLoader", "Delete " + pBase->TAG + " success.");
        delete pBase;
    });
    return plugin;
}

void PluginLoader::unload(const std::string &path, void *handle) const {
    if (!handle) {
        Log::e(TAG, "Unloaded plugin " + path + " failed.");
        return;
    }
    dlclose(handle);
    Log::d(TAG, "Unloaded plugin " + path + " success.");
}
